Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughCentralizes auth verification (JWT_SECRET + verifyJwtToken) to the server/proxy, removes page-level auth redirects, adds a client-side DashboardShell with sign-out and UI panels, and propagates JWT_SECRET through env, build scripts, and query-key utilities. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser (Client)
participant NextServer as NextJS Server / proxy
participant DashboardShell as Client (DashboardShell)
participant API as Auth API (/auth/logout)
participant QueryClient as react-query Cache
Browser->>NextServer: GET /dashboard
NextServer->>NextServer: verifyJwtToken(token, env.JWT_SECRET)
alt unauthenticated
NextServer-->>Browser: Redirect /auth/login
else authenticated
NextServer-->>Browser: Serve dashboard HTML (Layout + DashboardShell)
Browser->>DashboardShell: Hydrate/render shell (sidebar, header, badges)
end
note over Browser,DashboardShell: User triggers sign-out
Browser->>API: POST /auth/logout
API-->>Browser: 200 OK
Browser->>QueryClient: Invalidate `['auth','session','user']` and `['auth','session','jwt']`
Browser-->>Browser: Redirect to /
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
apps/next/app/(dashboard)/layout.tsx (1)
6-6: Add an explicit return type to the exported layout.Please annotate
Layoutwith an explicit return type, e.g.Promise<React.JSX.Element>, to keep exported functions explicit.Proposed change
-export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>) { +export default async function Layout( + { children }: Readonly<{ children: React.ReactNode }>, +): Promise<React.JSX.Element> {As per coding guidelines, "TypeScript practices: strict mode, no any, explicit return types for exported functions, type-only imports, and colocated schemas".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/app/`(dashboard)/layout.tsx at line 6, The exported async function Layout lacks an explicit return type; update its signature (the Layout function) to include an explicit return type such as Promise<React.JSX.Element> (or the appropriate JSX element type used in the app) so the declaration reads like: export default async function Layout(...): Promise<React.JSX.Element> { ... }; this satisfies the project's TypeScript guideline for explicit return types on exported functions.apps/next/app/(dashboard)/_dashboard-shell.tsx (1)
15-15: Add an explicit return type to the exported shell.Please annotate
DashboardShellwith an explicit return type, e.g.React.JSX.Element, so the public surface stays typed consistently.Proposed change
-export function DashboardShell({ children }: Readonly<{ children: React.ReactNode }>) { +export function DashboardShell( + { children }: Readonly<{ children: React.ReactNode }>, +): React.JSX.Element {As per coding guidelines, "TypeScript practices: strict mode, no any, explicit return types for exported functions, type-only imports, and colocated schemas".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/app/`(dashboard)/_dashboard-shell.tsx at line 15, Add an explicit return type to the exported component function by annotating DashboardShell's signature with React.JSX.Element (e.g. change "export function DashboardShell({ children }: Readonly<{ children: React.ReactNode }>)" to "export function DashboardShell({ children }: Readonly<{ children: React.ReactNode }>): React.JSX.Element" ); ensure any needed type-only import for React is used if your tsconfig requires it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/next/app/`(dashboard)/_dashboard-shell.tsx:
- Around line 29-30: The AuthBadge import in _dashboard-shell.tsx points to the
wrong package; update the import to the local component at
apps/next/components/shared/auth-badge.tsx (the AuthBadge component that uses
useUser()). Also modify the logout route handler (route.ts in app/auth/logout)
to explicitly invalidate the auth/session/user query cache after clearing
cookies by calling queryClient.invalidateQueries({ queryKey:
['auth','session','user'] })—follow the same pattern used in use-passkey-auth.ts
and use-link-email.ts so the badge updates immediately after logout.
In `@apps/next/app/`(dashboard)/layout.tsx:
- Around line 7-8: Layout is missing an explicit return type and getAuthStatus
performs decode-only JWT checks allowing forged tokens; add a return type (e.g.,
React.ReactNode or JSX.Element) to the Layout function signature and replace the
decode-only validation in getAuthStatus with proper signature verification using
jose's verifyJwt (or call a server action that runs verifyJwt on the token
server-side) so the cookie/JWT is cryptographically validated before rendering;
also update auth-server cookie creation to set httpOnly: true so the token is
not accessible to client-side JS.
---
Nitpick comments:
In `@apps/next/app/`(dashboard)/_dashboard-shell.tsx:
- Line 15: Add an explicit return type to the exported component function by
annotating DashboardShell's signature with React.JSX.Element (e.g. change
"export function DashboardShell({ children }: Readonly<{ children:
React.ReactNode }>)" to "export function DashboardShell({ children }: Readonly<{
children: React.ReactNode }>): React.JSX.Element" ); ensure any needed type-only
import for React is used if your tsconfig requires it.
In `@apps/next/app/`(dashboard)/layout.tsx:
- Line 6: The exported async function Layout lacks an explicit return type;
update its signature (the Layout function) to include an explicit return type
such as Promise<React.JSX.Element> (or the appropriate JSX element type used in
the app) so the declaration reads like: export default async function
Layout(...): Promise<React.JSX.Element> { ... }; this satisfies the project's
TypeScript guideline for explicit return types on exported functions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f069a509-1ab2-49e8-8b52-9638c6822cea
📒 Files selected for processing (4)
apps/next/app/(dashboard)/(news)/page.tsxapps/next/app/(dashboard)/_dashboard-shell.tsxapps/next/app/(dashboard)/layout.tsxapps/next/app/(dashboard)/markets/page.tsx
💤 Files with no reviewable changes (2)
- apps/next/app/(dashboard)/(news)/page.tsx
- apps/next/app/(dashboard)/markets/page.tsx
… return types - Replace decode-only JWT check with jose verifyJwt (crypto validation) - Add JWT_SECRET to Next env (server, prod-required) - Client-side logout with invalidateQueries for auth/session/user and jwt - Add explicit return types to Layout and DashboardShell - Add query-keys.ts for ESLint compliance, pass JWT_SECRET to e2e build
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
apps/next/lib/auth/auth-utils.ts (1)
29-33: Remove redundant expiration check.
verifyJwtToken()already validates theexpclaim viajwtVerify()(which throwsJWTExpiredif expired). The subsequentisTokenExpired()call on line 33 re-parses the raw token payload using identical logic (exp * 1000 <= Date.now()), making it redundant. Since no clock tolerance or custom date options are configured in either function, a token that passes verification cannot be expired. Delete theisTokenExpired()check and trust the verified payload.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/lib/auth/auth-utils.ts` around lines 29 - 33, The code redundantly re-checks token expiration after verification; remove the call to isTokenExpired({ token }) and its conditional return, because verifyJwtToken({ token, secret: env.JWT_SECRET }) already enforces the exp claim (throwing on expiry) and ensures decoded is valid; update the block around verifyJwtToken/decoded to rely on decoded.typ, decoded.sub, decoded.sid only and delete the isTokenExpired check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.gitleaks.toml:
- Line 31: Remove the broad allowlist entry '''scripts/run-qa\.mjs$''' in
.gitleaks.toml and instead add an allowlist rule that targets only the specific
sentinel string used as the placeholder JWT in scripts/run-qa.mjs (i.e., the
exact literal token or the constant name defined there), using a precise regex
or exact match so other secrets in that file remain detectable; update the rule
to reference that exact sentinel value rather than the whole filename.
In `@apps/next/app/`(dashboard)/_dashboard-shell.tsx:
- Around line 21-25: In handleSignOut, don't assume logout succeeded: check the
fetch('/auth/logout') response (use response.ok and/or response.status) and only
call queryClient.invalidateQueries(authSessionUserQueryKey |
authSessionJwtQueryKey) and set window.location.href='/' after a successful
response; on non-2xx responses, surface an error (throw, show UI toast, or
console.error) and avoid clearing client auth state or redirecting so the UI
remains consistent with the server session.
In `@apps/next/lib/auth/jwt-utils.ts`:
- Around line 33-39: Replace the manual base64 decode in isTokenExpired() with
the existing decodeJwtToken() helper: call decodeJwtToken(token) to get the
payload, then check payload.exp (convert to ms) to determine expiry; ensure you
handle a missing or unparsable payload by returning true (expired) and avoid
using atob() or direct token.split('.') decoding. Update references in
isTokenExpired() to use decodeJwtToken() and retain the same boolean semantics.
In `@apps/next/proxy.ts`:
- Around line 25-27: The proxy currently calls verifyJwtToken(...) (which uses
jwtVerify and enforces exp) and treats a null result as unauthenticated,
blocking the refresh path; change the flow so you first inspect the token
without enforcing expiration (either by using an existing isTokenExpired(token)
to decide refresh vs reject, or by decoding the token/verifying with expiration
ignored) to allow expired-but-refreshable tokens to reach the refresh logic,
then perform full verification (verifyJwtToken / jwtVerify) only after deciding
not to refresh; update the logic around verifyJwtToken, isTokenExpired and the
refresh decision so typ/sub/sid are checked from the decoded claims or after
ignoring exp, and only enforce exp when appropriate.
---
Nitpick comments:
In `@apps/next/lib/auth/auth-utils.ts`:
- Around line 29-33: The code redundantly re-checks token expiration after
verification; remove the call to isTokenExpired({ token }) and its conditional
return, because verifyJwtToken({ token, secret: env.JWT_SECRET }) already
enforces the exp claim (throwing on expiry) and ensures decoded is valid; update
the block around verifyJwtToken/decoded to rely on decoded.typ, decoded.sub,
decoded.sid only and delete the isTokenExpired check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 81722bce-fc39-4775-bcf8-2a65b0a004ac
⛔ Files ignored due to path filters (1)
apps/next/.env.productionis excluded by!**/.env*
📒 Files selected for processing (11)
.gitleaks.tomlapps/next/app/(dashboard)/_dashboard-shell.tsxapps/next/app/(dashboard)/layout.tsxapps/next/lib/auth/auth-utils.tsapps/next/lib/auth/jwt-utils.tsapps/next/lib/env.tsapps/next/lib/query-keys.tsapps/next/proxy.tsapps/next/scripts/run-e2e-local.mjsscripts/run-qa.mjsturbo.json
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/next/app/(dashboard)/layout.tsx
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/next/app/(dashboard)/layout.tsx (1)
3-6: Consider removingasyncsince noawaitis used.The function is marked
asyncbut doesn't perform any asynchronous operations. While harmless, removing it simplifies the signature.♻️ Suggested change
-export default async function Layout({ +export default function Layout({ children, -}: Readonly<{ children: React.ReactNode }>): Promise<React.JSX.Element> { +}: Readonly<{ children: React.ReactNode }>): React.JSX.Element { return <DashboardShell>{children}</DashboardShell> }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/app/`(dashboard)/layout.tsx around lines 3 - 6, The Layout function is marked async but contains no awaits; remove the async keyword and the Promise return type to make it a synchronous component: change the signature of Layout (currently "export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>): Promise<React.JSX.Element>") to a plain synchronous function returning React.JSX.Element (e.g., "export default function Layout(...) : React.JSX.Element") and keep using DashboardShell to render children..cursor/rules/frontend/auth.mdc (1)
3-3: Consider narrowing the glob pattern.The glob includes
packages/core/**andpackages/react/**, but the "Auth Protection (proxy.ts)" section is specific to Next.js route handling. Core and react packages shouldn't containgetAuthStatus()+redirect()patterns since they don't use Next.js routing. Consider whether this rule should apply only toapps/next/**.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.cursor/rules/frontend/auth.mdc at line 3, The glob pattern is too broad and may flag non-Next.js packages; narrow it so the "Auth Protection (proxy.ts)" rule only scans Next.js app code. Update the rule configuration to target only the Next.js app files (e.g., change the glob from including packages/core/** and packages/react/** to only apps/next/**) so the rule that looks for Next.js-specific symbols like getAuthStatus() and redirect() runs only against Next.js routes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In @.cursor/rules/frontend/auth.mdc:
- Line 3: The glob pattern is too broad and may flag non-Next.js packages;
narrow it so the "Auth Protection (proxy.ts)" rule only scans Next.js app code.
Update the rule configuration to target only the Next.js app files (e.g., change
the glob from including packages/core/** and packages/react/** to only
apps/next/**) so the rule that looks for Next.js-specific symbols like
getAuthStatus() and redirect() runs only against Next.js routes.
In `@apps/next/app/`(dashboard)/layout.tsx:
- Around line 3-6: The Layout function is marked async but contains no awaits;
remove the async keyword and the Promise return type to make it a synchronous
component: change the signature of Layout (currently "export default async
function Layout({ children }: Readonly<{ children: React.ReactNode }>):
Promise<React.JSX.Element>") to a plain synchronous function returning
React.JSX.Element (e.g., "export default function Layout(...) :
React.JSX.Element") and keep using DashboardShell to render children.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fda01595-ecb3-4fc2-abb6-24c184292dec
📒 Files selected for processing (4)
.cursor/rules/frontend/auth.mdcapps/docu/content/docs/architecture/authentication.mdxapps/next/app/(dashboard)/layout.tsxapps/next/app/auth/login/page.tsx
💤 Files with no reviewable changes (1)
- apps/next/app/auth/login/page.tsx
…esh flow - handleSignOut: check response.ok/status before invalidating and redirecting; surface toast on failure - isTokenExpired: use decodeJwtToken instead of manual base64/atob - proxy: decode token without exp first (decodeJwtToken), allow expired tokens to reach refresh; verifyJwtToken only when not refreshing
Summary by CodeRabbit
Refactor
New Features
Chores
Documentation